package com.run.bluetoothconnect;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

public class BluetoothClientActivity extends BaseActivity {

    //线程池,只连接一个吧，不搞这么复杂
    private final ExecutorService threadPool = Executors.newSingleThreadExecutor();

    private BluetoothAdapter mBluetoothAdapter;

    private BluetoothSocket socket;

    private EditText sendText;
    private Button sendButton;
    private EditText targetText;
    private Button targetButton;
    private TextView receiveText;

    private TextView stateText;
    private Button scanButton;
    private boolean isScaning = false;


    private RecyclerView recyclerView;
    private BaseRecyclerAdapter<BluetoothDevice> adapter;
    private final List<BluetoothDevice> deviceList = new CopyOnWriteArrayList<>();

    //要连接的目标蓝牙设备。
    private String targetDeviceName = "";

    private final String TAG = "蓝牙调试";
    private final String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB";

    // 广播接收发现蓝牙设备
    private boolean isRegisterReceiver = false;
    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @SuppressLint("SetTextI18n")
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
                    stateText.setText("searching...");
                    isScaning = true;

                    //清空列表
                    deviceList.clear();
                    adapter.notifyDataSetChanged();
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
                    stateText.setText("finished");
                    isScaning = false;
                    break;
                case BluetoothDevice.ACTION_FOUND:
                    //发现一个设备
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    //设备可能多次被发现
                    if (null != device && !deviceList.contains(device)) {
                        //添加到列表中，更新列表
                        deviceList.add(device);
                        adapter.notifyDataSetChanged();

                        //匹配是否是想要的目标
                        String name = device.getName();
                        if (name != null)
                            Log.d(TAG, "发现设备:" + name);

                        if (name != null && name.equals(targetDeviceName)) {
                            Log.d(TAG, "发现目标设备，开始线程连接!");
                            //蓝牙搜索是非常消耗系统资源开销的过程，一旦发现了目标感兴趣的设备，可以考虑关闭扫描。
                            //mBluetoothAdapter.cancelDiscovery();
                            connectDevice(device);
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    };

    //发送数据到另一端
    private void sendDataToServer(String data) {
        new Thread(() -> {
            try {
                OutputStream os = socket.getOutputStream();
                os.write(data.getBytes());
                os.flush();
                //os.close();
                runOnUiThread(() -> receiveText.append("发送消息->" +
                        socket.getRemoteDevice().getName() + ":\n\t\t\t\t" + data + "\n"));
            } catch (Exception e) {
                e.printStackTrace();
                runOnUiThread(() -> receiveText.append("发送消息:" + "失败！" + "\n"));
            }
        }).start();
    }

    @Override
    public void initParams(Bundle params) {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

    @Override
    public int bindLayout() {
        return R.layout.activity_bluetooth_client;
    }

    @Override
    public void initView(View view) {
        sendText = $(R.id.input);
        sendButton = $(R.id.send);
        receiveText = $(R.id.receive);

        targetText = $(R.id.target);
        targetButton = $(R.id.set);


        stateText = $(R.id.state);
        scanButton = $(R.id.scan);
        recyclerView = $(R.id.recycler);

    }

    @Override
    public void initData() {

    }

    @Override
    public void doBusiness(Context mContext) {
        //蓝牙适配器
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        //列表相关
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.addItemDecoration(
                new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        //设置适配器
        adapter = new BaseRecyclerAdapter<BluetoothDevice>(
                android.R.layout.simple_list_item_1, deviceList
        ) {
            @Override
            public void convertView(ViewHolder viewHolder, BluetoothDevice device, int position) {
                viewHolder.setText(android.R.id.text1, device.getName() + ":" + device.getAddress());
            }
        };
        //设置点击事件
        adapter.setOnItemClickListener((view1, device, position) -> new AlertDialog.Builder(this)
                .setTitle("")
                .setMessage("是否开始连接" + device.getName() + "？")
                .setPositiveButton("是", (dialog, which) -> {
                    //设置当前设备名
                    targetDeviceName = device.getName();
                    targetText.setText(targetDeviceName);
                    //连接蓝牙
                    connectDevice(device);
                })
                .setNegativeButton("否", null)
                .create()
                .show());
        recyclerView.setAdapter(adapter);

        //设置蓝牙目标，并开始连接
        targetButton.setOnClickListener(v -> {
            String deviceName = targetText.getText().toString();
            if (!TextUtils.isEmpty(deviceName)) {
                new AlertDialog.Builder(this)
                        .setTitle("")
                        .setMessage("是否开始连接" + deviceName + "？")
                        .setPositiveButton("是", (dialog, which) -> {
                            //先在扫描到的列表里面找
                            int index = -1;
                            for (int i = 0; i < deviceList.size(); i ++) {
                                BluetoothDevice device = deviceList.get(i);
                                String name = device.getName();//可能没有name
                                if (!TextUtils.isEmpty(name) && deviceName.equals(name)) {
                                    index = i;
                                    break;
                                }
                            }

                            if (index >= 0) {
                                //在扫描列表找到了
                                connectDevice(deviceList.get(index));
                            }else {
                                //扫描设备里面没有，就看已配对和再扫描了
                                connectDevice(deviceName);
                            }
                        })
                        .setNegativeButton("否", null)
                        .create()
                        .show();
            }
        });

        //发送消息
        sendButton.setOnClickListener(v -> {
            String data = sendText.getText().toString();
            if (!TextUtils.isEmpty(data)) {
                sendDataToServer(data);
            }
        });

        //手动启动扫描
        scanButton.setOnClickListener(v -> {
            if (!isScaning) {
                scanBlueTooth();
            }else {
                stopScan();
            }
        });

        //先在列表中显示已配对过设备
        addPairedDevices();
    }

    //添加已配对过设备
    private void addPairedDevices() {
        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        deviceList.addAll(pairedDevices);
        adapter.notifyDataSetChanged();
    }

    //通过设备名称连接蓝牙
    private void connectDevice(String deviceName) {
        //设置目标蓝牙设备名称
        targetDeviceName = deviceName;

        //从已连接设备中获取
        BluetoothDevice device = getPairedDevices(deviceName);
        if (device == null) {
            //启动蓝牙扫描，成功后匹配targetDeviceName，再连接
            scanBlueTooth();
        } else {
            connectDevice(device);
        }
    }

    private void scanBlueTooth() {
        //检查蓝牙是否开启
        if (!mBluetoothAdapter.isEnabled()) {
            new AlertDialog.Builder(this)
                    .setTitle("开启蓝牙")
                    .setMessage("当前设备蓝牙未开启，是否开启蓝牙？")
                    .setPositiveButton("是", (dialog, which) -> {
                        mBluetoothAdapter.enable();
                        startScan();
                    })
                    .setNegativeButton("否", null)
                    .create()
                    .show();
        }else {
            startScan();
        }
    }

    //扫描蓝牙设备
    private void startScan() {
        // 注册广播接收器，接收蓝牙发现讯息
        if (!isRegisterReceiver) {
            IntentFilter filter = new IntentFilter();

            //开始扫描
            filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
            //结束扫描
            filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
            //发现设备
            filter.addAction(BluetoothDevice.ACTION_FOUND);
            //状态变化
            filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

            registerReceiver(mBroadcastReceiver, filter);
            isRegisterReceiver = true;
        }

        if (mBluetoothAdapter.startDiscovery()) {
            receiveText.append("启动蓝牙扫描设备...\n");
            scanButton.setText("停止");
            isScaning = true;
        }
    }

    //停止扫描
    private void stopScan() {
        if (mBluetoothAdapter.isDiscovering()) {
            mBluetoothAdapter.cancelDiscovery();
            scanButton.setText("扫描");
            isScaning = false;
        }
    }

    //从已连接设备里面找
    private BluetoothDevice getPairedDevices(String deviceName) {
        // 获得和当前Android已经配对的蓝牙设备。
        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        if (pairedDevices != null && pairedDevices.size() > 0) {
            // 遍历
            for (BluetoothDevice device : pairedDevices) {
                // 把已经取得配对的蓝牙设备名字和地址打印出来。
                Log.d(TAG, device.getName() + " : " + device.getAddress());
                if (TextUtils.equals(deviceName, device.getName())) {
                    receiveText.append("已配对目标设备 -> " + deviceName + "\n");
                    return device;
                }
            }
        }

        return null;
    }

    //通过设备连接
    private void connectDevice(BluetoothDevice device) {

        //关闭已有socket
        if (null != socket) {
            try {
                socket.close();
                socket = null;
            }catch (Exception e) {
                e.printStackTrace();
                receiveText.append("关闭socket失败！\n");
                showToast("关闭socket失败！");
                return;
            }
        }

        //线程池执行,排队等待上一个单线程执行完毕
        threadPool.execute(() -> {
            try {
                socket = device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));
                socket.connect();
            } catch (IOException e) {
                e.printStackTrace();
                runOnUiThread(() -> receiveText.append("创建socket失败！\n"));
            }

            if (socket != null && socket.isConnected()) {
                runOnUiThread(() -> receiveText.append("创建socket成功！\n"));
                try {
                    InputStream inputStream;
                    while(socket != null) {

                        //随便写写
                        inputStream = socket.getInputStream();
                        byte[] buffer = new byte[2560];
                        int len = inputStream.read(buffer, 0, 2560);
                        if (len <= 0) {
                            //noinspection BusyWait
                            Thread.sleep(1000);
                            continue;
                        }

                        runOnUiThread(()->receiveText.append("收到消息->"
                                + socket.getRemoteDevice().getName() + ":\n\t\t\t\t" +
                                new String(buffer, 0, len) + "\n"));
                    }
                } catch(IOException e) {
                    e.printStackTrace();
                    Log.e("TAG", "startConnect: " + e.getMessage());
                    runOnUiThread(() -> receiveText.append("socket异常！\n"));
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            socket.close();
            if (isRegisterReceiver) {
                unregisterReceiver(mBroadcastReceiver);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}
